#include "Track.h"


Track::Track(void)
{
	World* w = World::instance();

	int step = TRACK_WIDTH;
	Vector2 current(-w->getSize()/2.0f + BORDER, w->getSize()/2.0f - BORDER);

	while(current.y > -w->getSize()/2.0f){
		tracks.push_back(std::vector<Vector2>());

		taken.push_back(false);

		Vector2 tmp = Vector2(current.x + 100, current.y);
		tracks[tracks.size()-1].push_back(current);
		while(tmp.x < w->getSize()/2.0f - BORDER){
			tracks[tracks.size()-1].push_back(tmp);
			tmp.x += 100;
		}
		tmp = Vector2(-current.x, current.y);
		tracks[tracks.size()-1].push_back(tmp);
		current.y -= step;

		if(current.y > -w->getSize()/2.0f){
			tmp = Vector2(-current.x, current.y);
			tracks[tracks.size()-1].push_back(tmp);
			tracks[tracks.size()-1].push_back(current);
			current.y -= step;
		}
	}

	current = Vector2(-w->getSize()/2.0f + BORDER, -w->getSize()/2.0f + BORDER);
	while(current.x < w->getSize()/2.0f){
		verticalTracks.push_back(std::vector<Vector2>());
		verticalTaken.push_back(false);

		Vector2 tmp = Vector2(current.x, -current.y);
		verticalTracks[verticalTracks.size()-1].push_back(current);
		verticalTracks[verticalTracks.size()-1].push_back(tmp);
		current.x += step;

		if(current.x < w->getSize()/2.0f){
			tmp = Vector2(current.x, -current.y);
			verticalTracks[verticalTracks.size()-1].push_back(tmp);
			verticalTracks[verticalTracks.size()-1].push_back(current);
			current.x += step;
		}
	}

	initialCleanup = false;
	ready = 0;
	tanks_done = 0;
}


Track::~Track(void)
{
}

bool Track::getNextTrack(std::vector<Vector2>* t, bool vertical){
	if(vertical)
		return getNextVerticalTrack(t);
	return getNextHorizontalTrack(t);
}

bool Track::getNextHorizontalTrack(std::vector<Vector2>* t){
	for(int i = 0; i < tracks.size(); i ++){
		if(!taken[i]){
			taken[i] = true;
			t->clear();
			t->insert(t->begin(), tracks[i].begin(), tracks[i].end());
			return true;
		}
	}
	return false;
}

bool Track::getNextVerticalTrack(std::vector<Vector2>* t){
	for(int i = 0; i < tracks.size(); i ++){
		if(!verticalTaken[i]){
			verticalTaken[i] = true;
			t->clear();
			t->insert(t->begin(), verticalTracks[i].begin(), verticalTracks[i].end());
			return true;
		}
		
	}
	return false;
}

void Track::unsetTrackTaken(int index){
	taken[index] = false;
}

void Track::initialize(){
	initialCleanup = true;
	
	World::instance()->getGraph()->SearchForUnexplored(&missed);
	
	vector<Vector2> corners = World::instance()->getCorners();
	bool add = false;

	for(int i = 0; i < corners.size(); i ++){
		node* n = World::instance()->getGraph()->getNode(corners[i]);
		for(int ii = 0; ii < n->neighbors.size(); ii ++){
			add = true;
			node* next = n->neighbors[ii].to;
			if(!next->occupied && next->explored){
				//missed.push_back(Vector2(next->x, next->y));
				//break;
				for(int j = 0; j < missed.size(); j ++){
					if((missed[j] - Vector2(next->x, next->y)).magnitude() < 10){
						add = false;
						break;
					}
				}
				if(add){
					missed.push_back(Vector2(next->x, next->y));
					break;
				}
			}
		}
	}
	//missed.insert(missed.end(), corners.begin(), corners.end());

	explored.resize(missed.size());

	for(int i = 0; i < missed.size(); i ++)
		explored[i] = false;
}

bool Track::initialized(){
	return initialCleanup;
}

bool Track::getNextMissedNode(Vector2* v, Vector2 position){
	int index = -1;
	float dist = -1;;
	float current;

	for(int i = 0; i < missed.size(); i ++){
		if(!explored[i]){
			current = (missed[i] - position).magnitude();
			if(dist == -1){
				dist = (missed[i] - position).magnitude();
				index = i;
				continue;
			}
			if(current < dist){
				dist = current;
				index = i;
			}
			//(*v) = missed[i];
			//explored[i] = true;
			//std::cout << i << endl;
			//return true;
		}
	}
	if(index == -1)
		return false;
	explored[index] = true;
	(*v) = missed[index];
	return true;
}

void Track::markReady(){
	ready++;
}

bool Track::isReady(){
	return (ready >= World::instance()->tanksP()->size());
}

void Track::markDone(){
	tanks_done ++;
}

bool Track::isDone(){
	return (tanks_done >= World::instance()->tanksP()->size());
}

std::vector<Vector2> Track::getCleanupPoints(){
	if(!initialCleanup)
		return vector<Vector2>();
	return missed;
}